//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <winhack.h>
#include "framebuffer.h"

void CFrameBuffer::Underlay_Overlay2BufferCopy_YCbCr422()
{
    WORD *pDesBuffer;
    BYTE * pTransArray;

    BYTE *pY, *pCb, *pCr;
    int RGB_R, RGB_G, RGB_B;
    int YCbCr_Y, YCbCr_Cb, YCbCr_Cr;

    WORD SrcPixelRed, SrcPixelGreen, SrcPixelBlue;
    WORD BlendPixelRed, BlendPixelGreen, BlendPixelBlue;

    pTransArray = m_pTransArray + m_overlay2.PosX +
                    m_overlay2.PosY * m_screenWidth;

    pDesBuffer = (WORD *)m_pSurface->pixels +
                    (m_screenPosY + m_overlay2.PosY) *
                    m_mobileWidth + m_screenPosX +
                    m_overlay2.PosX;

    pY = (BYTE *)m_overlay2.pChannelFb[0];
    pCb = (BYTE *)m_overlay2.pChannelFb[1];
    pCr = (BYTE *)m_overlay2.pChannelFb[2];

    for (int j = 0; j < m_overlay2.Height; j++) {
        for (int i = 0; i < m_overlay2.Width; i++) {
            if(0 == *pTransArray) {
                pTransArray++;
                pDesBuffer++;
                continue;
            }

            //Get the overlay2 RGB
            YCbCr_Y = (int)pY[i + j * m_overlay2.Width];
            YCbCr_Cb = (int)pCb[(i + j * m_overlay2.Width) / 2];
            YCbCr_Cr = (int)pCr[(i + j * m_overlay2.Width) / 2];

            RGB_R = (int)(YCbCr_Y + 1.402 * (YCbCr_Cr - 128));
            RGB_G = (int)(YCbCr_Y - 0.344 * (YCbCr_Cb - 128) - 0.714 * (YCbCr_Cr - 128));
            RGB_B = (int)(YCbCr_Y + 1.773 * (YCbCr_Cb - 128));

            if (RGB_R < 0) RGB_R = 0;
            if (RGB_R > 0xFF) RGB_R = 0xFF;

            if (RGB_G < 0) RGB_G = 0;
            if (RGB_G > 0xFF) RGB_G = 0xFF;

            if (RGB_B < 0) RGB_B = 0;
            if (RGB_B > 0xFF) RGB_B = 0xFF;

            //Full Trans
            if(*pDesBuffer == 0) {
                *pDesBuffer = ((RGB_R & 0xF8) << 8) | ((RGB_G & 0xFC) << 3) | (RGB_B >> 3);
                pTransArray++;
                pDesBuffer++;
                continue;
            }

            //Blend the pixel with setted desbuffer and overlay2 RGB
            SrcPixelRed = (*pDesBuffer & 0xF800) >> 8;
            SrcPixelGreen = (*pDesBuffer & 0x07E0) >> 3;
            SrcPixelBlue = (*pDesBuffer & 0x001F) << 3;

            switch(m_nTransparencyKey) {
                case 0://8/8
                    BlendPixelRed = SrcPixelRed;
                    BlendPixelGreen = SrcPixelGreen;
                    BlendPixelBlue = SrcPixelBlue;
                    break;
                case 1://7/8
                    BlendPixelRed = (WORD)((SrcPixelRed * 7/8)
                        + (RGB_R >> 3));
                    BlendPixelGreen = (WORD)((SrcPixelGreen * 7/8)
                        + (RGB_G >> 3));
                    BlendPixelBlue = (WORD)((SrcPixelBlue * 7/8)
                        + (RGB_B >> 3));
                    break;
                case 2://6/8
                    BlendPixelRed = (WORD)((SrcPixelRed * 2/3)
                        + RGB_R * 1/3);
                    BlendPixelGreen = (WORD)((SrcPixelGreen * 2/3)
                        + RGB_G * 1/3);
                    BlendPixelBlue = (WORD)((SrcPixelBlue * 2/3)
                        + RGB_B * 1/3);
                    break;
                case 3://5/8
                    BlendPixelRed = (WORD)((SrcPixelRed * 5/8)
                        + RGB_R * 3/8);
                    BlendPixelGreen = (WORD)((SrcPixelGreen * 5/8)
                        + RGB_G * 3/8);
                    BlendPixelBlue = (WORD)((SrcPixelBlue * 5/8)
                        + RGB_B * 3/8);
                    break;
                case 4://4/8
                    BlendPixelRed = (WORD)((SrcPixelRed >> 1)
                        + RGB_R  - (RGB_R >> 1));
                    BlendPixelGreen = (WORD)((SrcPixelGreen >> 1)
                        + RGB_G  - (RGB_G >> 1));
                    BlendPixelBlue = (WORD)((SrcPixelBlue >> 1)
                        + RGB_B  - (RGB_B >> 1));
                    break;
                case 5://3/8
                    BlendPixelRed = (WORD)(((SrcPixelRed >> 3) * 3)
                        + (RGB_R >> 3) * 5);
                    BlendPixelGreen = (WORD)(((SrcPixelGreen >> 3) * 3)
                        + (RGB_G >> 3) * 5);
                    BlendPixelBlue = (WORD)(((SrcPixelBlue >> 3) * 3)
                        + (RGB_B >> 3) * 5);
                    break;
                case 6://2/8
                    BlendPixelRed = (WORD)((SrcPixelRed >> 2)
                        + RGB_R  - (RGB_R >> 2));
                    BlendPixelGreen = (WORD)((SrcPixelGreen >> 2)
                        + RGB_G  - (RGB_G >> 2));
                    BlendPixelBlue = (WORD)((SrcPixelBlue >> 2)
                        + RGB_B  - (RGB_B >> 2));
                    break;
                case 7://1/8
                    // Improve efficiency
                default:
                    BlendPixelRed = (WORD)((SrcPixelRed >> 3)
                        + RGB_R  - (RGB_R >> 3));
                    BlendPixelGreen = (WORD)((SrcPixelGreen >> 3)
                        + RGB_G  - (RGB_G >> 3));
                    BlendPixelBlue = (WORD)((SrcPixelBlue >> 3)
                        + RGB_B  - (RGB_B >> 3));
                    break;
            }
            *pDesBuffer = ((BlendPixelRed & 0xF8) << 8) | ((BlendPixelGreen & 0xFC) << 3) | (BlendPixelBlue >> 3);

            pTransArray++;
            pDesBuffer++;
        }
        pTransArray += (m_screenWidth - m_overlay2.Width);
        pDesBuffer += (m_mobileWidth - m_overlay2.Width);
    }
}


void CFrameBuffer::Underlay_Overlay2BufferCopy_YCbCr420()
{
    WORD *pDesBuffer;
    BYTE * pTransArray;

    BYTE *pY, *pCb, *pCr;
    int RGB_R, RGB_G, RGB_B;
    int YCbCr_Y, YCbCr_Cb, YCbCr_Cr;

    WORD SrcPixelRed, SrcPixelGreen, SrcPixelBlue;
    WORD BlendPixelRed, BlendPixelGreen, BlendPixelBlue;

    pTransArray = m_pTransArray + m_overlay2.PosX +
                    m_overlay2.PosY * m_screenWidth;

    pDesBuffer = (WORD *)m_pSurface->pixels +
                    (m_screenPosY + m_overlay2.PosY) *
                    m_mobileWidth + m_screenPosX +
                    m_overlay2.PosX;

    pY = (BYTE *)m_overlay2.pChannelFb[0];
    pCb = (BYTE *)m_overlay2.pChannelFb[1];
    pCr = (BYTE *)m_overlay2.pChannelFb[2];

    for (int j = 0; j < m_overlay2.Height; j++) {
        for (int i = 0; i < m_overlay2.Width; i++) {
            if(0 == *pTransArray) {
                pTransArray++;
                pDesBuffer++;
                continue;
            }

            //Get the overlay2 RGB
            YCbCr_Y = (int)pY[i + j * m_overlay2.Width];
            YCbCr_Cb = (int)pCb[(i + (j/2) * m_overlay2.Width) / 2];
            YCbCr_Cr = (int)pCr[(i + (j/2) * m_overlay2.Width) / 2];

            RGB_R = (int)(YCbCr_Y + 1.402 * (YCbCr_Cr - 128));
            RGB_G = (int)(YCbCr_Y - 0.344 * (YCbCr_Cb - 128) - 0.714 * (YCbCr_Cr - 128));
            RGB_B = (int)(YCbCr_Y + 1.773 * (YCbCr_Cb - 128));

            if (RGB_R < 0) RGB_R = 0;
            if (RGB_R > 0xFF) RGB_R = 0xFF;

            if (RGB_G < 0) RGB_G = 0;
            if (RGB_G > 0xFF) RGB_G = 0xFF;

            if (RGB_B < 0) RGB_B = 0;
            if (RGB_B > 0xFF) RGB_B = 0xFF;

            //Full Trans
            if(*pDesBuffer == 0) {
                *pDesBuffer = ((RGB_R & 0xF8) << 8) | ((RGB_G & 0xFC) << 3) | (RGB_B >> 3);
                pTransArray++;
                pDesBuffer++;
                continue;
            }

            //Blend the pixel with setted desbuffer and overlay2 RGB
            SrcPixelRed = (*pDesBuffer & 0xF800) >> 8;
            SrcPixelGreen = (*pDesBuffer & 0x07E0) >> 3;
            SrcPixelBlue = (*pDesBuffer & 0x001F) << 3;

            switch(m_nTransparencyKey) {
                case 0://8/8
                    BlendPixelRed = SrcPixelRed;
                    BlendPixelGreen = SrcPixelGreen;
                    BlendPixelBlue = SrcPixelBlue;
                    break;
                case 1://7/8
                    BlendPixelRed = (WORD)((SrcPixelRed * 7/8)
                        + (RGB_R >> 3));
                    BlendPixelGreen = (WORD)((SrcPixelGreen * 7/8)
                        + (RGB_G >> 3));
                    BlendPixelBlue = (WORD)((SrcPixelBlue * 7/8)
                        + (RGB_B >> 3));
                    break;
                case 2://6/8
                    BlendPixelRed = (WORD)((SrcPixelRed * 2/3)
                        + RGB_R * 1/3);
                    BlendPixelGreen = (WORD)((SrcPixelGreen * 2/3)
                        + RGB_G * 1/3);
                    BlendPixelBlue = (WORD)((SrcPixelBlue * 2/3)
                        + RGB_B * 1/3);
                    break;
                case 3://5/8
                    BlendPixelRed = (WORD)((SrcPixelRed * 5/8)
                        + RGB_R * 3/8);
                    BlendPixelGreen = (WORD)((SrcPixelGreen * 5/8)
                        + RGB_G * 3/8);
                    BlendPixelBlue = (WORD)((SrcPixelBlue * 5/8)
                        + RGB_B * 3/8);
                    break;
                case 4://4/8
                    BlendPixelRed = (WORD)((SrcPixelRed >> 1)
                        + RGB_R  - (RGB_R >> 1));
                    BlendPixelGreen = (WORD)((SrcPixelGreen >> 1)
                        + RGB_G  - (RGB_G >> 1));
                    BlendPixelBlue = (WORD)((SrcPixelBlue >> 1)
                        + RGB_B  - (RGB_B >> 1));
                    break;
                case 5://3/8
                    BlendPixelRed = (WORD)(((SrcPixelRed >> 3) * 3)
                        + (RGB_R >> 3) * 5);
                    BlendPixelGreen = (WORD)(((SrcPixelGreen >> 3) * 3)
                        + (RGB_G >> 3) * 5);
                    BlendPixelBlue = (WORD)(((SrcPixelBlue >> 3) * 3)
                        + (RGB_B >> 3) * 5);
                    break;
                case 6://2/8
                    BlendPixelRed = (WORD)((SrcPixelRed >> 2)
                        + RGB_R  - (RGB_R >> 2));
                    BlendPixelGreen = (WORD)((SrcPixelGreen >> 2)
                        + RGB_G  - (RGB_G >> 2));
                    BlendPixelBlue = (WORD)((SrcPixelBlue >> 2)
                        + RGB_B  - (RGB_B >> 2));
                    break;
                case 7://1/8
                    // Improve efficiency
                default:
                    BlendPixelRed = (WORD)((SrcPixelRed >> 3)
                        + RGB_R  - (RGB_R >> 3));
                    BlendPixelGreen = (WORD)((SrcPixelGreen >> 3)
                        + RGB_G  - (RGB_G >> 3));
                    BlendPixelBlue = (WORD)((SrcPixelBlue >> 3)
                        + RGB_B  - (RGB_B >> 3));
                    break;
            }
            *pDesBuffer = ((BlendPixelRed & 0xF8) << 8) | ((BlendPixelGreen & 0xFC) << 3) | (BlendPixelBlue >> 3);

            pTransArray++;
            pDesBuffer++;
        }
        pTransArray += (m_screenWidth - m_overlay2.Width);
        pDesBuffer += (m_mobileWidth - m_overlay2.Width);
    }

}

void CFrameBuffer::Overlay_Overlay2BufferCopy_YCbCr422()
{
    WORD *pDesBuffer;
    BYTE *pY, *pCb, *pCr;
    int RGB_R, RGB_G, RGB_B;
    int YCbCr_Y, YCbCr_Cb, YCbCr_Cr;

    pDesBuffer = (WORD *)m_pSurface->pixels +
                    (m_screenPosY + m_overlay2.PosY) *
                    m_mobileWidth + m_screenPosX +
                    m_overlay2.PosX;

    pY = (BYTE *)m_overlay2.pChannelFb[0];
    pCb = (BYTE *)m_overlay2.pChannelFb[1];
    pCr = (BYTE *)m_overlay2.pChannelFb[2];

    for (int j = 0; j < m_overlay2.Height; j++) {
        for (int i = 0; i < m_overlay2.Width; i++) {
            YCbCr_Y = (int)pY[i + j * m_overlay2.Width];
            YCbCr_Cb = (int)pCb[(i + j * m_overlay2.Width) / 2];
            YCbCr_Cr = (int)pCr[(i + j * m_overlay2.Width) / 2];

            RGB_R = (int)(YCbCr_Y + 1.402 * (YCbCr_Cr - 128));
            RGB_G = (int)(YCbCr_Y - 0.344 * (YCbCr_Cb - 128) - 0.714 * (YCbCr_Cr - 128));
            RGB_B = (int)(YCbCr_Y + 1.773 * (YCbCr_Cb - 128));

            if (RGB_R < 0) RGB_R = 0;
            if (RGB_R > 0xFF) RGB_R = 0xFF;

            if (RGB_G < 0) RGB_G = 0;
            if (RGB_G > 0xFF) RGB_G = 0xFF;

            if (RGB_B < 0) RGB_B = 0;
            if (RGB_B > 0xFF) RGB_B = 0xFF;

            *pDesBuffer =
                    ((RGB_R & 0xF8) << 8) | ((RGB_G & 0xFC) << 3) | (RGB_B >> 3);
            pDesBuffer++;
        }
        pDesBuffer += (m_mobileWidth - m_overlay2.Width);
    }
}

void CFrameBuffer::Overlay_Overlay2BufferCopy_YCbCr420()
{
    WORD *pDesBuffer;
    BYTE *pY, *pCb, *pCr;
    int RGB_R, RGB_G, RGB_B;
    int YCbCr_Y, YCbCr_Cb, YCbCr_Cr;

    pDesBuffer = (WORD *)m_pSurface->pixels +
                    (m_screenPosY + m_overlay2.PosY) *
                    m_mobileWidth + m_screenPosX +
                    m_overlay2.PosX;

    pY = (BYTE *)m_overlay2.pChannelFb[0];
    pCb = (BYTE *)m_overlay2.pChannelFb[1];
    pCr = (BYTE *)m_overlay2.pChannelFb[2];

    for (int j = 0; j < m_overlay2.Height; j++) {
        for (int i = 0; i < m_overlay2.Width; i++) {
            YCbCr_Y = (int)pY[i + j * m_overlay2.Width];
            YCbCr_Cb = (int)pCb[(i + (j/2) * m_overlay2.Width) / 2];
            YCbCr_Cr = (int)pCr[(i + (j/2) * m_overlay2.Width) / 2];

            RGB_R = (int)(YCbCr_Y + 1.402 * (YCbCr_Cr - 128));
            RGB_G = (int)(YCbCr_Y - 0.344 * (YCbCr_Cb - 128) - 0.714 * (YCbCr_Cr - 128));
            RGB_B = (int)(YCbCr_Y + 1.773 * (YCbCr_Cb - 128));

            if (RGB_R < 0) RGB_R = 0;
            if (RGB_R > 0xFF) RGB_R = 0xFF;

            if (RGB_G < 0) RGB_G = 0;
            if (RGB_G > 0xFF) RGB_G = 0xFF;

            if (RGB_B < 0) RGB_B = 0;
            if (RGB_B > 0xFF) RGB_B = 0xFF;

            *pDesBuffer =
                    ((RGB_R & 0xF8) << 8) | ((RGB_G & 0xFC) << 3) | (RGB_B >> 3);
            pDesBuffer++;
        }
        pDesBuffer += (m_mobileWidth - m_overlay2.Width);
    }
}


